/*
 * @Version: V1.0
 * @Project: MGS组件 All rights Reserved, Designed By www.supermap.com
 * @Title: 经纬网
 * @Package: mgs-webui-basic
 * @Description:
 * @Author: 李卫欣
 * @Date: 2021-06-20 17:29:07
 * @Copyright: 2021 www.supermap.com Inc. All rights reserved.
 * @注意: 本内容仅限于北京超图信息技术有限公司内部传阅，禁止外泄以及用于其他的商业目的
 */
import type { BindMap } from 'types'
import L from 'leaflet'

export default class GraticulesPlugin {
    static extends = [
        'openGraticules', //开启经纬网
        'closeGraticules', //关闭经纬网
        'openGLabel', //开启经纬网注记(没有经纬网时，会开启经纬网)
        'closeGLabel', //关闭经纬网注记
    ]

    //注记显示开关
    private showGLable__!: Boolean

    //地图对象leaflet
    private map: any

    //内存绘制层
    private graticulesGroup__ = L.layerGroup()

    //内存绘注记制层
    private gLabelGroup__ = L.layerGroup()

    //经纬网显示开关
    private isOpen__ = false

    //当前视口范围
    private currentBounds__!: L.LatLngBounds

    //当前视口比例
    private currentZoomLvl__ = 1

    //插件归属的vue对象
    private vmParent: any

    //经纬网 样式
    private graticulesStyle__: any

    constructor(vm: BindMap) {
        this.vmParent = vm
        this.map = vm.map
        this.graticulesGroup__.addTo(this.map)
        this.gLabelGroup__.addTo(this.map)
        this.currentBounds__ = this.map.getBounds()
        this.currentZoomLvl__ = this.map.getZoom()
    }

    /**
     * 打开经纬网
     */
    openGraticules(isLabel: boolean = false, style: any) {
        this.isOpen__ = true
        this.showGLable__ = isLabel
        this.graticulesStyle__ = style
        this.map.on('zoomend', this._onMapZoomEnd, this)
        this.map.on('moveend', this._onMapMoveEnd, this)
        this.drawGraticules(this.map.getZoom(), this.map.getBounds())
    }

    /**
     * 关闭经纬网
     */
    closeGraticules() {
        this.isOpen__ = false
        this.showGLable__ = false
        this.graticulesStyle__ = {}
        this.map.off('zoomend', this._onMapZoomEnd)
        this.map.off('moveend', this._onMapMoveEnd)
        this.graticulesGroup__.clearLayers()
        this.gLabelGroup__.clearLayers()
    }

    /**
     * 打开经纬网注记
     */
    openGLabel() {
        this.showGLable__ = true
        this.closeGraticules()
        this.openGraticules(true, this.graticulesStyle__)
    }

    /**
     * 关闭经纬网注记
     */
    closeGLabel() {
        this.showGLable__ = false
        // this.closeGraticules()
        // this.openGraticules()
        this.gLabelGroup__.clearLayers()
    }

    /**
     * 地图比例尺改变事件
     * @param e
     * @returns
     */
    _onMapZoomEnd(e: any) {
        this.currentBounds__ = e.target.getBounds()
        this.currentZoomLvl__ = e.target.getZoom()
        if (!this.isOpen__) {
            return
        }
        this.drawGraticules(e.target.getZoom(), e.target.getBounds())
    }

    /**
     * 地图中心点改变事件
     * @param e
     * @returns
     */
    _onMapMoveEnd(e: any) {
        this.currentBounds__ = e.target.getBounds()
        this.currentZoomLvl__ = e.target.getZoom()
        if (!this.isOpen__) {
            return
        }
        this.drawGraticules(e.target.getZoom(), e.target.getBounds())
    }

    /**
     * 绘制经纬网
     * @param zoomLvl 当前级别
     * @param bounds 当前范围
     */
    drawGraticules(zoomLvl: number, bounds: L.LatLngBounds) {
        let w: number = bounds.getWest()
        let s: number = bounds.getSouth()
        let e: number = bounds.getEast()
        let n: number = bounds.getNorth()
        //取跨度
        let step: number = 1
        if (this.currentZoomLvl__ < 3) {
            step = 10
        } else if (this.currentZoomLvl__ < 6) {
            step = 5
        }
        const lbW = w
        const lbN = n
        //直接取整 w s
        w = Math.floor(w)
        s = Math.floor(s)
        switch (step) {
            case 5:
                w = Math.floor(w / 5) * 5
                s = Math.floor(s / 5) * 5
                break
            case 10:
                w = Math.floor(w / 10) * 10
                s = Math.floor(s / 10) * 10
                break
        }
        if (w < -180) {
            w = -180
        }
        if (s < -90) {
            s = -90
        }
        //取整加1 e n
        e = Math.ceil(e)
        if (e > 180) {
            e = 180
        }
        n = Math.ceil(n)
        if (n > 90) {
            n = 90
        }
        //清除原网格
        this.graticulesGroup__.clearLayers()
        this.gLabelGroup__.clearLayers()
        //设置风格样式
        const selfStyle = Object.assign(
            {
                color: '#999999',
                fillColor: 'transparent',
                weight: 0.5,
                'font-size': '16px',
                'font-weight': 600,
            },
            this.graticulesStyle__
        )
        this.graticulesStyle__ = selfStyle
        //开始画网格
        const self = this
        let r = 0,
            c = 0
        for (let lng = w; lng < e + 1 && lng < 181; lng += step) {
            for (let lat = s; lat < n + 1 && lat < 91; lat += step) {
                L.polygon(
                    [
                        [lat, lng],
                        [lat + step, lng],
                        [lat + step, lng + step],
                        [lat, lng + step],
                    ],
                    selfStyle
                )
                    .addTo(this.graticulesGroup__)
                    .on('click', function (e) {
                        self.vmParent.$emit('GraticulesClick', e)
                    })
                if (this.showGLable__) {
                    // 拼接样式字符串
                    let styleHtml = ``
                    for (const key in selfStyle) {
                        styleHtml += `${key}:${selfStyle[key]};`
                    }
                    if (r === 1) {
                        //纬度
                        L.marker([lat, lbW], {
                            icon: L.divIcon({
                                className: '',
                                html: `<span style='margin-left:10px;${styleHtml}'>${lat}°</span>`,
                            }),
                        }).addTo(this.graticulesGroup__)
                    }
                    if (c === 1) {
                        //经度
                        L.marker([lbN, lng], {
                            icon: L.divIcon({
                                className: '',
                                html: `<span style='margin-top:5px;display:inline-block;${styleHtml}'>${lng}°</span>`,
                            }),
                        }).addTo(this.graticulesGroup__)
                    }
                }
                c++
            }
            r++
            c = 0
        }
    }
}
